home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
3D GFX
/
3D GFX.iso
/
amiutils
/
i_l
/
irit5
/
cagd_lib
/
cbzreval.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-30
|
17KB
|
391 lines
/******************************************************************************
* CBzrEval.c - Bezier curves handling routines - evaluation routines. *
*******************************************************************************
* Written by Gershon Elber, Mar. 90. *
******************************************************************************/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "cagd_loc.h"
static int PowerCacheFineNess,
BezierCacheEnabled = FALSE,
CacheFineNess = 0;
static CagdRType *BezierCache[CAGD_MAX_BEZIER_CACHE_ORDER + 1]
[CAGD_MAX_BEZIER_CACHE_ORDER + 1];
static int IChooseK[CAGD_MAX_BEZIER_CACHE_ORDER + 1]
[CAGD_MAX_BEZIER_CACHE_ORDER + 1] =
{
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 4, 6, 4, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 5, 10, 10, 5, 1, 0, 0, 0, 0, 0 },
{ 1, 6, 15, 20, 15, 6, 1, 0, 0, 0, 0 },
{ 1, 7, 21, 35, 35, 21, 7, 1, 0, 0, 0 },
{ 1, 8, 28, 56, 70, 56, 28, 8, 1, 0, 0 },
{ 1, 9, 36, 84, 126, 126, 84, 36, 9, 1, 0 },
{ 1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1 }
};
static CagdRType BzrCrvEvalFuncAux(int i, int k, CagdRType t);
static CagdRType IntPow(CagdRType x, int i);
/*****************************************************************************
* DESCRIPTION: M
* Sets the bezier sampling cache - if enabled, a Bezier can be evaluated M
* directly from presampled basis function. M
* *
* PARAMETERS: M
* FineNess: Number of samples to support (power of 2). M
* EnableCache: Are we really planning on using this thing? M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* BzrCrvSetCache, evaluation, caching M
*****************************************************************************/
void BzrCrvSetCache(int FineNess, CagdBType EnableCache)
{
int i, j, k;
if (BezierCacheEnabled == EnableCache && FineNess == CacheFineNess)
return;
if (BezierCacheEnabled) {
/* Free old cache if was one. */
for (k = 2; k <= CAGD_MAX_BEZIER_CACHE_ORDER; k++)
for (i = 0; i < k; i++)
if (BezierCache[k][i] != NULL) {
IritFree((VoidPtr) BezierCache[k][i]);
BezierCache[k][i] = NULL;
}
}
if ((BezierCacheEnabled = EnableCache) != FALSE) {
/* Allocate the new cache and initalize it: */
if (FineNess < 2)
FineNess = 2;
if (FineNess > CAGD_MAX_BEZIER_CACHE_FINENESS)
FineNess = CAGD_MAX_BEZIER_CACHE_FINENESS;
CacheFineNess = FineNess;
PowerCacheFineNess = 1 << FineNess;
for (k = 2; k <= CAGD_MAX_BEZIER_CACHE_ORDER; k++)/* For all orders. */
for (i = 0; i < k; i++) { /* Allocate and set all basis func. */
BezierCache[k][i] = (CagdRType *)
IritMalloc(sizeof(CagdRType) * PowerCacheFineNess);
for (j = 0; j < PowerCacheFineNess; j++)
BezierCache[k][i][j] = BzrCrvEvalFuncAux(i, k,
((CagdRType) j) / (PowerCacheFineNess - 1));
}
}
}
/*****************************************************************************
* DESCRIPTION: M
* Assumes Vec holds control points for scalar bezier curve of order Order, M
* and evaluates and returns that curve value at parameter value t. M
* Vec is incremented by VecInc (usually by 1) after each iteration. M
* *
* PARAMETERS: M
* Vec: Coefficents of a scalar Bspline univariate function. M
* VecInc: Step to move along Vec. M
* Order: Order of associated geometry. M
* t: Parameter value where to evaluate the curve. M
* *
* RETURN VALUE: M
* CagdRType: Geometry's value at parameter value t. M
* *
* KEYWORDS: M
* BzrCrvEvalVecAtParam, evaluation M
*****************************************************************************/
CagdRType BzrCrvEvalVecAtParam(CagdRType *Vec,
int VecInc,
int Order,
CagdRType t)
{
int i;
CagdRType
R = 0.0;
if (VecInc == 1)
for (i = 0; i < Order; i++)
R += BzrCrvEvalFuncAux(i, Order, t) * *Vec++;
else
for (i = 0; i < Order; i++) {
R += BzrCrvEvalFuncAux(i, Order, t) * *Vec;
Vec += VecInc;
}
return R;
}
/*****************************************************************************
* DESCRIPTION: M
* Returns a pointer to a static data, holding the value of the curve at M
* given parametric location t. The curve is assumed to be Bezier. M
* *
* PARAMETERS: M
* Crv: To evaluate at the given parametric location t. M
* t: The parameter value at which the curve Crv is to be evaluated. M
* *
* RETURN VALUE: M
* CagdRType *: A vector holding all the coefficients of all components M
* of curve Crv's point type. If for example the curve's M
* point type is P2, the W, X, and Y will be saved in the M
* first three locations of the returned vector. The first M
* location (index 0) of the returned vector is reserved for M
* the rational coefficient W and XYZ always starts at second M
* location of the returned vector (index 1). M
* *
* KEYWORDS: M
* BzrCrvEvalAtParam, evaluation M
*****************************************************************************/
CagdRType *BzrCrvEvalAtParam(CagdCrvStruct *Crv, CagdRType t)
{
static CagdRType Pt[CAGD_MAX_PT_COORD];
CagdBType
IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
int i, j,
k = Crv -> Order,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
CagdRType B;
for (j = IsNotRational; j <= MaxCoord; j++)
Pt[j] = 0.0;
for (i = 0; i < k; i++) {
B = BzrCrvEvalFuncAux(i, k, t);
for (j = IsNotRational; j <= MaxCoord; j++)
Pt[j] += B * Crv -> Points[j][i];
}
return Pt;
}
/*****************************************************************************
* DESCRIPTION: M
* Samples the curve at FineNess location equally spaced in the curve's M
* parametric domain. M
* *
* PARAMETERS: M
* Crv: To approximate as a polyline. M
* FineNess: Control on number of samples. M
* Points: Where to put the resulting polyline. M
* A: Optional alpha matrix for refinement. M
* *
* RETURN VALUE: M
* int: The actual number of samples placed in Points. Always M
* less than or eaul to FineNess. M
* *
* KEYWORDS: M
* BzrCrvEvalToPolyline, conversion, refinement, evaluation M
*****************************************************************************/
void BzrCrvEvalToPolyline(CagdCrvStruct *Crv,
int FineNess,
CagdRType *Points[])
{
CagdBType
UseCache = BezierCacheEnabled &&
FineNess == PowerCacheFineNess &&
Crv -> Order <= CAGD_MAX_BEZIER_CACHE_ORDER,
IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
int i, j, Count,
k = Crv -> Order,
MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
CagdRType B;
if (UseCache) {
for (Count = 0; Count < PowerCacheFineNess; Count++) {
for (j = IsNotRational; j <= MaxCoord; j++)
Points[j][Count] = 0.0;
for (i = 0; i < k; i++) {
B = BezierCache[k][i][Count];
for (j = IsNotRational; j <= MaxCoord; j++)
Points[j][Count] += B * Crv -> Points[j][i];
}
}
}
else {
for (Count = 0; Count < FineNess; Count++) {
for (j = IsNotRational; j <= MaxCoord; j++)
Points[j][Count] = 0.0;
for (i = 0; i < k; i++) {
B = BzrCrvEvalFuncAux(i, k,
((CagdRType) Count) / (FineNess - 1));
for (j = IsNotRational; j <= MaxCoord; j++)
Points[j][Count] += Crv -> Points[j][i] * B;
}
}
}
}
/*****************************************************************************
* DESCRIPTION: *
* Evaluates the i'th Bezier basis function of order k, at parametric value t *
* (t in [0..1]). *
* This function is: i k - i - 1 i *
* Bi,k(t) = ( ) * t * (1 - t) *
* k *
* *
* PARAMETERS: *
* i: I'th basi function. *
* k: Degree of the curve. *
* t: Parameter value at which to evaluate the Bezier basis function. *
* *
* RETURN VALUE: *
* CagdRType: Value of the i'th Bezier basis function of degree k at t. *
*****************************************************************************/
static CagdRType BzrCrvEvalFuncAux(int i, int k, CagdRType t)
{
if (APX_EQ(t, 0.0))
return (CagdRType) (i == 0);
else if (APX_EQ(t, 1.0))
return (CagdRType) (i == k - 1);
else
return (k >= CAGD_MAX_BEZIER_CACHE_ORDER ?
CagdIChooseK(i, k - 1) : (CagdRType) IChooseK[k - 1][i]) *
IntPow(1.0 - t, k - i - 1) * IntPow(t, i);
}
/*****************************************************************************
* DESCRIPTION: *
* Computes x to the power of i, i integer. *
* *
* *
* PARAMETERS: *
* x, i: Description says it all. *
* *
* RETURN VALUE: *
* CagdRType: Integer power of x, computed using pwoer of 2's. *
*****************************************************************************/
static CagdRType IntPow(CagdRType x, int i)
{
CagdRType Power, RetVal;
for (Power = x, RetVal = 1.0; i != 0; i >>= 1) {
if (i & 0x01)
RetVal *= Power;
Power = SQR(Power);
}
return RetVal;
}
/*****************************************************************************
* DESCRIPTION: M
* Evaluates the following (in floating point arithmetic): M
* k k! V
* ( ) = ------------- V
* i i! * (k - i)! V
* *
* PARAMETERS: M
* i, k: Coefficients of i choose k. M
* *
* RETURN VALUE: M
* CagdRType: Result of i choose k, in floating point, to prevent from M
* overflows. M
* *
* KEYWORDS: M
* CagdIChooseK, evaluation, combinatorics M
*****************************************************************************/
CagdRType CagdIChooseK(int i, int k)
{
int j;
CagdRType
c = 1.0;
if ((k >> 1) > i) { /* i is less than half of k: */
for (j = k - i + 1; j <= k; j++)
c *= j;
for (j = 2; j <= i; j++)
c /= j;
}
else {
for (j = i + 1; j <= k; j++)
c *= j;
for (j = 2; j <= k - i; j++)
c /= j;
}
return c;
}
#ifdef K_CHOOSE_I_GEN
/*****************************************************************************
* DESCRIPTION: *
* Evaluate the following (in integer arithmetic): *
* k k! *
* ( ) = ------------- *
* i i! * (k - i)! *
* *
* PARAMETERS: *
* i, k: Coefficients of i choose k. *
* *
* RETURN VALUE: *
* int: Result of i choose k. *
*****************************************************************************/
static int IChooseKGenOne(int i, int k)
{
int j;
long c = 1;
if ((k >> 1) > i) { /* i is less than half of k: */
for (j = k - i + 1; j <= k; j++)
c *= j;
for (j = 2; j <= i; j++)
c /= j;
}
else {
for (j = i + 1; j <= k; j++)
c *= j;
for (j = 2; j <= k - i; j++)
c /= j;
}
return (int) c;
}
/*****************************************************************************
* DESCRIPTION: *
* Evaluates IChooseK for all possiblities and prints them for the *
* IChooseK table defined in the beginning of this file. *
* *
* PARAMETERS: *
* None *
* *
* RETURN VALUE: *
* void *
*****************************************************************************/
void IChooseKGen(void)
{
int i, j;
for (i = 0; i <= MAX_BEZIER_CACHE_ORDER; i++) {
printf(" },\n {");
for (j = 0; j <= MAX_BEZIER_CACHE_ORDER; j++)
printf(" %4d,", j <= i ? IChooseKGenOne(j ,i) : 0);
}
}
/*****************************************************************************
* DESCRIPTION: *
* Main routine to create the table in the beginning of this file. *
* PARAMETERS: *
* None *
* *
* RETURN VALUE: *
* void *
*****************************************************************************/
void main(void)
{
IChooseKGen();
}
#endif /* K_CHOOSE_I_GEN */